# utils/json_modifier.py
import json
import copy
from datetime import datetime
from typing import Dict, Any, List, Optional


class JSONModifier:
    """JSON修改工具，负责安全修改JSON结构并管理修改记录"""
    
    def __init__(self, max_history: int = 3):
        """
        初始化JSON修改器
        
        Args:
            max_history: 最大修改历史记录数，默认3次
        """
        self.max_history = max_history
    
    def apply_modification(self, json_data: Dict[str, Any], modification: Dict[str, Any], 
                          modification_log: List[Dict[str, Any]], add_history: bool = True) -> Dict[str, Any]:
        """
        应用修改到JSON数据并记录修改历史
        
        Args:
            json_data: 原始JSON数据
            modification: 修改指令，包含action, target, value等
            modification_log: 修改记录列表
            
        Returns:
            修改后的JSON数据
        """
        # 深拷贝避免修改原数据
        new_data = copy.deepcopy(json_data)
        
        # 记录修改前的状态
        backup_data = copy.deepcopy(json_data)
        
        try:
            # 根据修改类型执行操作
            action = modification.get('action')
            target = modification.get('target')
            
            if action == 'delete':
                self._delete_item(new_data, target)
            elif action == 'add':
                self._add_item(new_data, modification)
            elif action == 'update':
                self._update_item(new_data, modification)
            else:
                raise ValueError(f"不支持的修改操作: {action}")
            
            # 记录修改历史（可选）
            if add_history:
                self._add_to_history(modification_log, {
                    'action': action,
                    'target': target,
                    'old_value': self._extract_target_value(backup_data, target) if target else None,
                    'new_value': self._extract_target_value(new_data, target) if target else modification.get('value'),
                    'timestamp': datetime.now().isoformat(),
                    'backup_data': backup_data  # 保存完整备份用于回滚
                })
            
            return new_data
            
        except Exception as e:
            raise ValueError(f"修改失败: {str(e)}")

    def begin_snapshot(self, json_data: Dict[str, Any]) -> Dict[str, Any]:
        """为一次交互开始创建快照备份（深拷贝）。"""
        return copy.deepcopy(json_data)

    def commit_snapshot(self, modification_log: List[Dict[str, Any]], backup_data: Dict[str, Any],
                         action: str = 'batch', target: str = 'multi', description: Optional[str] = None) -> None:
        """
        将一次交互级别的快照写入历史，仅添加一条记录。

        Args:
            modification_log: 历史记录列表
            backup_data: 交互前的完整备份
            action: 历史摘要的动作名称，默认 'batch'
            target: 历史摘要的目标名称，默认 'multi'
            description: 可选描述
        """
        record = {
            'action': action,
            'target': target,
            'old_value': None,
            'new_value': None,
            'timestamp': datetime.now().isoformat(),
            'backup_data': backup_data,
        }
        if description:
            record['description'] = description
        self._add_to_history(modification_log, record)
    
    def rollback_last_modification(self, modification_log: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
        """
        回滚最后一次修改
        
        Args:
            modification_log: 修改记录列表
            
        Returns:
            回滚后的JSON数据，如果没有可回滚的记录则返回None
        """
        if not modification_log:
            return None
        
        # 获取最后一次修改记录
        last_modification = modification_log.pop()
        return last_modification.get('backup_data')
    
    def _delete_item(self, json_data: Dict[str, Any], target: str):
        """删除指定项目"""
        items = json_data.get('items', [])
        original_count = len(items)
        
        # 支持按ID、索引或模块删除
        if target.startswith('id:'):
            item_id = target[3:]  # 去掉 'id:' 前缀
            json_data['items'] = [item for item in items if item.get('id') != item_id]
        elif target.startswith('index:'):
            try:
                index = int(target[6:])  # 去掉 'index:' 前缀
                if 0 <= index < len(items):
                    items.pop(index)
                else:
                    raise ValueError(f"索引超出范围: {index}")
            except ValueError:
                raise ValueError(f"无效的索引格式: {target}")
        elif target.startswith('module:'):
            module_name = target[7:]  # 去掉 'module:' 前缀
            json_data['items'] = [item for item in items if item.get('module') != module_name]
        else:
            raise ValueError(f"无效的删除目标: {target}。支持格式: id:项目ID, index:索引号, module:模块名")
        
        # 检查是否有项目被删除
        new_count = len(json_data.get('items', []))
        if new_count == original_count:
            if target.startswith('module:'):
                raise ValueError(f"未找到模块 '{target[7:]}' 的任何项目")
            elif target.startswith('id:'):
                raise ValueError(f"未找到ID为 '{target[3:]}' 的项目")
            else:
                raise ValueError(f"删除操作未生效")
    
    def _add_item(self, json_data: Dict[str, Any], modification: Dict[str, Any]):
        """添加新项目"""
        new_item = modification.get('value', {})
        
        # 验证必需字段
        required_fields = ['id', 'module', 'category', 'checkpoint', 'materials']
        for field in required_fields:
            if field not in new_item:
                raise ValueError(f"缺少必需字段: {field}")
        
        # 检查ID是否重复
        existing_ids = [item.get('id') for item in json_data.get('items', [])]
        if new_item['id'] in existing_ids:
            raise ValueError(f"ID已存在: {new_item['id']}")
        
        # 添加到items列表
        if 'items' not in json_data:
            json_data['items'] = []
        json_data['items'].append(new_item)
    
    def _update_item(self, json_data: Dict[str, Any], modification: Dict[str, Any]):
        """更新现有项目"""
        target = modification.get('target')
        updates = modification.get('value', {})
        
        items = json_data.get('items', [])
        
        if target.startswith('id:'):
            item_id = target[3:]
            for item in items:
                if item.get('id') == item_id:
                    item.update(updates)
                    return
            raise ValueError(f"未找到ID为 {item_id} 的项目")
        elif target.startswith('index:'):
            try:
                index = int(target[6:])
                if 0 <= index < len(items):
                    items[index].update(updates)
                else:
                    raise ValueError(f"索引超出范围: {index}")
            except ValueError:
                raise ValueError(f"无效的索引: {target}")
        else:
            raise ValueError(f"无效的更新目标: {target}")
    
    def _extract_target_value(self, json_data: Dict[str, Any], target: str) -> Any:
        """提取目标值用于记录"""
        items = json_data.get('items', [])
        
        if target.startswith('id:'):
            item_id = target[3:]
            for item in items:
                if item.get('id') == item_id:
                    return item
        elif target.startswith('index:'):
            try:
                index = int(target[6:])
                if 0 <= index < len(items):
                    return items[index]
            except (ValueError, IndexError):
                pass
        elif target.startswith('module:'):
            module_name = target[7:]
            # 返回该模块的所有项目
            module_items = [item for item in items if item.get('module') == module_name]
            return module_items if module_items else None
        
        return None
    
    def _add_to_history(self, modification_log: List[Dict[str, Any]], record: Dict[str, Any]):
        """添加修改记录到历史，保持最大记录数限制"""
        modification_log.append(record)
        
        # 如果超过最大记录数，删除最早的记录
        while len(modification_log) > self.max_history:
            modification_log.pop(0)
    
    def get_history_summary(self, modification_log: List[Dict[str, Any]]) -> str:
        """获取修改历史摘要"""
        if not modification_log:
            return "暂无修改记录"
        
        summary = "最近的修改记录:\n"
        for i, record in enumerate(reversed(modification_log[-3:]), 1):
            action = record.get('action', '未知')
            target = record.get('target', '未知')
            timestamp = record.get('timestamp', '')
            summary += f"{i}. {action} - {target} ({timestamp[:19]})\n"
        
        return summary


# 创建全局修改器实例
json_modifier = JSONModifier()
